/* eslint-disable no-undef */
import React, { useEffect, useState, useRef } from "react";
import { Canvas } from "@react-three/fiber"; // 基于Three.js的React渲染器
import { OrbitControls } from "@react-three/drei"; // 轨道控制器（相机交互）
import * as THREE from "three"; // Three.js核心库
import { Select } from "antd"; // 蚂蚁设计下拉选择框
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader.js"; // GLTF模型加载器
import "./index.css"; // 本地样式文件

// 声明Webkit语音识别类型（解决TypeScript类型报错）
declare global {
  interface Window {
    webkitSpeechRecognition: any; // 兼容Chrome的语音识别API
  }
}

// 动画索引字典类型（动作名称映射到动画索引）
interface AnimationDict {
  [key: string]: number; // 键为动作名称，值为动画索引
}

function Ai() {
  // 模型文件路径（使用公共路径，需确保文件存在于public/models目录）
  const [modelUrl] = useState<string>("/public/models/wjm.glb");
  // 模型加载状态
  const [isModelLoaded, setIsModelLoaded] = useState<boolean>(false);
  // 当前动画索引（用于切换动作）
  const [index, setIndex] = useState<number>(0);
  // 模型包含的动画片段数组
  const [selectedAction, setSelectedAction] = useState<THREE.AnimationClip[]>([]);
  // 拖拽框DOM引用（用于控制按钮组位置）
  const dragbox = useRef<HTMLDivElement>(null);
  // 语音识别状态
  const [isListening, setIsListening] = useState<boolean>(false);

  // 语音识别对象引用
  const recognition = useRef<any>(null);
  // 模型对象引用（Three.js Group）
  const modelRef = useRef<THREE.Group | null>(null);
  // 动画混合器引用（管理模型动画）
  const mixerRef = useRef<THREE.AnimationMixer | null>(null);
  // 当前播放的动画动作
  let currentAction: THREE.AnimationAction | null = null;

  // ------------------------------
  // 拖拽框移动逻辑（鼠标按下事件）
  // ------------------------------
  useEffect(() => {
    const handleMouseDown = (e: MouseEvent) => {
      if (!dragbox.current) return; // 确保DOM已挂载

      // 获取拖拽框位置和鼠标偏移量
      const rect = dragbox.current.getBoundingClientRect();
      const x = e.pageX - rect.left;
      const y = e.pageY - rect.top;

      // 鼠标移动时更新拖拽框位置
      const handleMouseMove = (e: MouseEvent) => {
        if (!dragbox.current) return;
        dragbox.current.style.left = `${e.pageX - x}px`;
        dragbox.current.style.top = `${e.pageY - y}px`;
      };

      // 鼠标松开时移除事件监听
      const handleMouseUp = () => {
        document.removeEventListener("mousemove", handleMouseMove);
        document.removeEventListener("mouseup", handleMouseUp);
      };

      // 绑定全局事件
      document.addEventListener("mousemove", handleMouseMove);
      document.addEventListener("mouseup", handleMouseUp);
    };

    // 挂载时绑定事件，卸载时移除
    const currentDragbox = dragbox.current;
    if (currentDragbox) {
      currentDragbox.addEventListener("mousedown", handleMouseDown);
    }

    return () => {
      if (currentDragbox) {
        currentDragbox.removeEventListener("mousedown", handleMouseDown);
      }
    };
  }, [dragbox]); // 依赖项变化时重新绑定事件

  // ------------------------------
  // 下拉框选项变化处理
  // ------------------------------
  const handleChange = (value: string) => {
    // 动作名称到动画索引的映射（需与模型动画顺序一致）
    const indexMap: AnimationDict = {
      "累了躺一会儿": 0,
      "站着不动": 1,
      "跑起来": 3,
      "吓我一跳": 2,
    };
    setIndex(indexMap[value]); // 更新动画索引
  };

  // ------------------------------
  // 语音识别初始化（仅执行一次）
  // ------------------------------
  useEffect(() => {
    if ("webkitSpeechRecognition" in window) { // 检查浏览器支持
      recognition.current = new window.webkitSpeechRecognition();
      recognition.current.continuous = true; // 持续识别
      recognition.current.interimResults = true; // 返回临时结果
      recognition.current.lang = "zh-CN"; // 设置中文识别

      // 识别结果处理
      recognition.current.onresult = (event: any) => {
        const transcript = event.results[event.resultIndex][0].transcript.trim(); // 提取识别文本
        // 根据关键词触发动作切换
        if (transcript.includes("累了躺一会儿")) handleChange("累了躺一会儿");
        else if (transcript.includes("站着不动")) handleChange("站着不动");
        else if (transcript.includes("跑起来")) handleChange("跑起来");
        else if (transcript.includes("吓我一跳")) handleChange("吓我一跳");
      };

      // 识别结束处理
      recognition.current.onend = () => {
        setIsListening(false); // 停止监听状态
      };
    }
  }, []); // 仅在组件挂载时执行一次

  // ------------------------------
  // 开始语音识别
  // ------------------------------
  const startListening = () => {
    if (recognition.current) {
      recognition.current.start(); // 启动识别
      setIsListening(true); // 更新状态
    }
  };

  // ------------------------------
  // 停止语音识别
  // ------------------------------
  const stopListening = () => {
    if (recognition.current) {
      recognition.current.stop(); // 停止识别
      setIsListening(false); // 更新状态
    }
  };

  // ------------------------------
  // 模型加载与动画控制
  // ------------------------------
  useEffect(() => {
    const loader = new GLTFLoader(); // 创建GLTF加载器
    let animationFrameId: number; // 动画帧ID

    // 加载模型
    loader.load(
      modelUrl,
      (gltf) => {
        const loadedModel = gltf.scene; // 获取模型场景对象
        setSelectedAction(gltf.animations); // 保存动画片段
        setIsModelLoaded(true); // 标记模型已加载

        // 检查模型是否包含动画
        if (!gltf.animations?.length) {
          console.error("模型没有动画！");
          return;
        }

        // 确保索引不越界
        const safeIndex = Math.min(index, gltf.animations.length - 1);
        if (index !== safeIndex) {
          setIndex(safeIndex); // 修正非法索引
          return;
        }

        const clip = gltf.animations[safeIndex]; // 获取当前动画片段
        const scale = 2.5; // 模型缩放比例
        loadedModel.scale.set(scale, scale, scale); // 设置缩放
        loadedModel.position.set(0, -2, 0); // 设置位置（调整Y轴避免模型陷入地面）
        modelRef.current = loadedModel; // 保存模型引用

        // 创建动画混合器
        mixerRef.current = new THREE.AnimationMixer(loadedModel);

        // 播放动画
        if (mixerRef.current && clip) {
          const action = mixerRef.current.clipAction(clip); // 创建动画动作
          action.timeScale = 0.4; // 播放速度（0.4倍速）
          action.clampWhenFinished = true; // 动画结束后保持最后一帧
          action.play(); // 开始播放
          currentAction = action; // 保存当前动作
        }

        // 动画循环函数（更新混合器）
        const animate = () => {
          animationFrameId = requestAnimationFrame(animate); // 请求下一帧
          mixerRef.current?.update(0.01); // 更新动画（时间增量）
        };
        animate(); // 启动动画循环
      },
      undefined, // 加载进度回调（此处忽略）
      (error) => {
        console.error("模型加载失败:", error); // 错误处理
      }
    );

    // 组件卸载时清理资源
    return () => {
      if (animationFrameId) cancelAnimationFrame(animationFrameId); // 停止动画循环
      mixerRef.current?.stopAllAction(); // 停止所有动画
    };
  }, [modelUrl, index]); // 模型路径或索引变化时重新加载/切换动画

  return (
    <div className="aaa">
      {/* Three.js渲染画布 */}
      <Canvas>
        <ambientLight intensity={3} /> {/* 环境光 */}
        <directionalLight position={[10, 10, 10]} intensity={3} /> {/* 方向光 */}
        {/* 渲染模型（仅在加载完成后显示） */}
        {modelRef.current && (
          <>
            <primitive object={modelRef.current} /> {/* 渲染Three.js对象 */}
            <OrbitControls /> {/* 轨道控制器（允许鼠标拖拽旋转视角） */}
          </>
        )}
        {/* 额外的轨道控制器（可能重复，建议检查是否需要） */}
        <OrbitControls />
      </Canvas>
      {/* 可拖拽的控制按钮组 */}
      <div className="button-container" ref={dragbox}>
        {/* 动作切换下拉框 */}
        <Select
          defaultValue="切换动作"
          style={{ width: 120 }}
          onChange={handleChange}
          options={[
            { value: "累了躺一会儿" },
            { value: "站着不动" },
            { value: "跑起来" },
            { value: "吓我一跳" },
          ]}
        />
        {/* 语音控制按钮 */}
        <button onClick={startListening} disabled={isListening}>
          {isListening ? "正在监听..." : "开始语音控制"}
        </button>
        <button onClick={stopListening} disabled={!isListening}>
          停止语音控制
        </button>
      </div>
    </div>
  );
}

export default Ai;